package com.core.ui.controller;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.core.managers.LoginManager;
import com.core.managers.SessionManager;
import com.core.protocols.IAuthenticationDelegate;
import com.core.protocols.ICustomDatasourceDelegate;
import com.core.protocols.IServiceLayerDelegate;
import com.core.protocols.ITabSheetDatasource;
import com.core.servicelayer.TabSheetServiceLayer;
import com.core.ui.actionscript.ActionScriptParser;
import com.core.ui.controller.base.ServletDependenceController;
import com.core.ui.customcell.TabSheetItemCell;
import com.core.utils.GlobalConstants;
import com.core.utils.HibernateParameter;
import com.model.ActionScript;
import com.model.KeyValue;
import com.model.TabSheetItem;

public class TabSheetController
        extends ServletDependenceController
        implements ITabSheetDatasource, IServiceLayerDelegate {

	private String align = "vertical";



	public String getAlign () {

		return align;
	}



	public void setAlign ( String align ) {

		this.align = align;
	}



	@Override
	public String tabsPanelStyleClassName () {

		return String.format("tabspanel tabspanel_%s", this.align);
	}

	private ICustomDatasourceDelegate delegate;


	TabSheetServiceLayer              tabSheetServiceLayer = null;
	String                            selectedJSPName      = null;

	ArrayList <TabSheetItemCell>      tabsheetCells        = null;

	private IAuthenticationDelegate   authenticationDelegate;



	public IAuthenticationDelegate getAuthenticationDelegate () {

		return authenticationDelegate;
	}



	public void setAuthenticationDelegate ( IAuthenticationDelegate authenticationDelegate ) {

		this.authenticationDelegate = authenticationDelegate;
	}



	public TabSheetController() {

		authenticationDelegate = null;
	}



	// *********************************************************
	// * TableViewDataSource
	// *********************************************************

	@Override
	public TabSheetItemCell tabSheetCellAtIndex ( int index ) {

		return tabsheetCells.get(index);
	}



	/**
	 * ICustomDatasource
	 * 
	 * 
	 * 
	 */

	@Override
	public void setCustomDatasourceDelegate ( ICustomDatasourceDelegate delegate ) {

		this.delegate = delegate;

	}



	@Override
	public void reloadData () {

		SessionManager sessionManager = SessionManager.sharedInstance();
		String servletName = sessionManager.servletName();

		String script = "";
		script += " join TabSheetItem.userContextNameToExecute as UCN_ToExecute,";
		script += " com.model.user.User as User";
		script += " join User.userCategory.userRole.availableContexts as availableUCN";
		script += " where UCN_ToExecute IN (availableUCN)";
		script += " and User.id=:ID";
		script += String.format(" and servletNameToExecute = '%s'", servletName);

		Set <HibernateParameter> params = new HashSet <HibernateParameter>();
		params.add(new HibernateParameter("ID", LoginManager.sharedInstance().getUserId()));
		tabSheetServiceLayer = new TabSheetServiceLayer();
		tabSheetServiceLayer.setLayerDelegate(this);
		tabSheetServiceLayer.performRequestWithFilter(script, params);
	}



	/**
     *
     *
     *
     *
     *
     */
	public String selectedJspNameInContext () {

		String result = this.selectedJSPName;

		return result;
	}



	@Override
	public int tabSheetCellsCount () {

		return tabsheetCells.size();
	}



	// TODO: refactor this
	private Boolean isSelectedCellWithPojo ( TabSheetItem pojo ) {

		SessionManager sessionManager = SessionManager.sharedInstance();
		String servletQuery = sessionManager.currentRequestQueryString();

		if ( servletQuery == null ) {
			return false;
		}
		Boolean isSelected = true;

		ArrayList <KeyValue> servletParamValuesAsId = this.currentServletParamValueAsId();

		ActionScript actionScript = pojo.getActionScript();
		assert (actionScript == null) : "action script could not be null";

		Set <KeyValue> actionScriptParams = actionScript.getParams();


		String[] servletQueryAsArray = servletQuery.split("&");
		for ( String servletQueryAsArrayItem : servletQueryAsArray ) {
			String[] servletParam = servletQueryAsArrayItem.split("=");

			if ( servletParamValuesAsId.size() != 0 ) {
				Boolean isID = false;
				for ( KeyValue keyvalue : servletParamValuesAsId ) {
					isID = (servletParam[0].equals(keyvalue.getKey()));
					if ( isID ) {
						continue;
					}
					for ( KeyValue actionScriptParam : actionScriptParams ) {
						if ( !(GlobalConstants.ACTIONSCRIPT_USERINFO_PARAM_KEY.equalsIgnoreCase(actionScriptParam.getUserInfo())) ) {
							isSelected &= (actionScriptParam.getValue().equalsIgnoreCase(servletQueryAsArrayItem));
						}
					}

				}

			} else {
				for ( KeyValue actionScriptParam : actionScriptParams ) {
					if ( !(GlobalConstants.ACTIONSCRIPT_USERINFO_PARAM_KEY.equalsIgnoreCase(actionScriptParam.getUserInfo())) ) {
						isSelected &= (actionScriptParam.getValue().equalsIgnoreCase(servletQueryAsArrayItem));
					}
				}
			}
		}
		return isSelected;
	}



	private TabSheetItemCell newCellFromTabSheetItem ( TabSheetItem pojo,
	                                                   int index,
	                                                   int itemsCount ) {

		TabSheetItemCell result = new TabSheetItemCell();

		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("tabview_link");
		stringBuilder.append(String.format(" tabview_link-%s ", this.align));

		Boolean isLast = (index == (itemsCount - 1));
		if ( isLast ) {
			stringBuilder.append(String.format(" tabview_link_last-%s", this.align));
		}

		Boolean isFirst = (index == 0);
		if ( isFirst ) {
			stringBuilder.append(String.format(" tabview_link_first-%s", this.align));
		}

		Boolean isSelected = this.isSelectedCellWithPojo(pojo);
		if ( isSelected ) {
			stringBuilder.append(String.format(" tabview_link_selected-%s", this.align));
		}

		result.setName(pojo.getName());

		String linkURL = null;
		String onClickEvent = null;

		ActionScript actionScript = pojo.getActionScript();
		if ( actionScript != null ) {
			String script = actionScript.getActionScriptText();
			String scriptType = actionScript.getActionScriptType();

			Set <KeyValue> actionScriptParams = actionScript.getParams();
			for ( KeyValue param : actionScriptParams ) {
				if ( actionScriptParser != null ) {
					String paramValue = null;
					try {
						paramValue = actionScriptParser.parseActionScriptParam(param);
					} catch ( Exception e ) {
						paramValue = "?";
					}
					script = script.replaceAll("\\{" + param.getKey() + "\\}", paramValue);
				} else {
					script = script.replaceAll("\\{" + param.getKey() + "\\}", param.getValue());
				}
			}

			if ( scriptType.equalsIgnoreCase("javascript") ) {
				onClickEvent = script;
			} else {
				linkURL = script;
			}
		}

		result.setLinkURL(linkURL);
		result.setOnClickEvent(onClickEvent);

		result.setStyleClassName(stringBuilder.toString());
		result.setLinkStyleClassName("tabview_link_refrerence");

		result.setSelected(isSelected);

		if ( isSelected ) {
			this.selectedJSPName = pojo.getJspNameInContext();
		}

		// -----------------------------------------------------------
		return result;
	}



	@Override
	public <T> void responseResponseItemsList ( final List <T> items,
	                                            final Object request,
	                                            final Exception exception ) {

		tabsheetCells = new ArrayList <TabSheetItemCell>();
		if ( exception != null ) {
			return;
		}

		if ( items == null ) {
			return;
		}

		this.selectedJSPName = "";
		int itemsCount = items.size();

		int i = 0;
		for ( T item : items ) {
			TabSheetItemCell cell = this.newCellFromTabSheetItem((TabSheetItem) item, i, itemsCount);
			tabsheetCells.add(cell);
			i++;

		}

		if ( delegate != null ) {
			delegate.refreshContent();
		}
	}

	private ActionScriptParser actionScriptParser;



	public void setActionScriptParser ( ActionScriptParser actionScriptParser ) {

		this.actionScriptParser = actionScriptParser;

		if ( this.actionScriptParser == null ) {
			return;
		}


		this.addServletParamNameAsId(actionScriptParser.entityIdentifierName());

	}

}
